use std::{collections::HashMap, ptr::null, str::FromStr};

use super::*;

#[derive(Debug, Clone, PartialEq)]
pub enum JsonValue {
    JsonString(String),
    JsonNumber(f32),
    JsonBool(bool),
    JsonNull,
    JsonUndefined,
    JsonArray(Vec<JsonValue>),
    JsonObject(HashMap<String, JsonValue>),
}

impl FromStr for JsonValue {
    type Err = String;

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        use JsonValue::*;

        let null_parser = tag("null").map(|_| JsonNull);
        let bool_parser = tag("true")
            .or(tag("false"))
            .map(|b: String| JsonBool(b.parse().unwrap()));

        let json_parser = null_parser.or(bool_parser);

        match json_parser.run(s) {
            Ok((jv, remaining)) => {
                if remaining.is_empty() {
                    Ok(jv)
                } else {
                    Err(format!("unknonw {}", remaining))
                }
            }
            Err(err) => Err(err),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use JsonValue::*;

    #[test]
    fn test_json_null() {
        assert_eq!("null".parse::<JsonValue>().unwrap(), JsonNull);
    }
}
